package com.smm.web.vmc.service.impl;

import com.smm.web.vmc.dao.BaseDao;
import com.smm.web.vmc.domain.Pager;
import com.smm.web.vmc.domain.Warehouse;
import com.smm.web.vmc.domain.WarehouseImage;
import com.smm.web.vmc.dto.WarehouseDto;
import com.smm.web.vmc.service.WarehouseService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.hibernate.Criteria;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by zhenghao on 2016/9/5.
 *
 */
@Slf4j
@Service
public class WarehouseServiceImpl implements WarehouseService {

    @Resource
    private BaseDao<Warehouse> warehouseBaseDao;

    @Resource
    private BaseDao<WarehouseImage> warehouseImageBaseDao;

    @Override
    public List<Warehouse> getAll() {

        return warehouseBaseDao.getAll(Warehouse.class);
    }

    @Override
    @Transactional
    public List<WarehouseDto> getAllForDto() {
        String sql = "SELECT warehouse.*, COUNT(DISTINCT tag.`no`) AS tagNumber , COUNT(DISTINCT receipt.`no`) AS receiptNumber , COUNT( DISTINCT camera.id) AS cameraNumber " +
                "FROM warehouse \nLEFT JOIN tag ON tag.`warehouse_id`= warehouse.`id`\nLEFT JOIN camera ON camera.`warehouse_id` = warehouse.`id`\n " +
                "LEFT JOIN receipt ON receipt.`warehouse_id` = warehouse.`id`\nGROUP BY warehouse.`id` order by warehouse.`id` desc \n";
        List result = this.warehouseBaseDao.createSqlQuery(sql);

        if(result==null || result.size()==0) return null;

        return getWarehouseDtoListByResult(result);
    }

    @Override
    public void add(Warehouse warehouse) throws Exception {

        this.warehouseBaseDao.add(warehouse);
    }

    @Override
    @Transactional
    public void add(Warehouse warehouse, String imageList) throws Exception {

        this.warehouseBaseDao.add(warehouse);

        this.addWarehouseImage(imageList,warehouse);

    }

    @Override
    public void update(Warehouse warehouse) throws Exception {

        this.warehouseBaseDao.update(warehouse);
    }

    @Override
    @Transactional
    public void update(Warehouse warehouse, String imageList) throws Exception {

        this.warehouseBaseDao.update(warehouse);

        if(StringUtils.isNotBlank(imageList)){

            //删除仓库已有图片
            for (WarehouseImage image : this.getImageListByid(warehouse.getId())){

                this.warehouseImageBaseDao.delete(image);
            }

            //新增仓库图片
            this.addWarehouseImage(imageList,warehouse);

        }


    }


    //仓库批量新增图片
    private void addWarehouseImage(String imageList, Warehouse warehouse) {

        if(StringUtils.isNotBlank(imageList)){

            for(String imageUrl:imageList.split(";")){

                WarehouseImage image = new WarehouseImage();

                image.setImageUrl(imageUrl);
                image.setWarehouse(warehouse);

                this.warehouseImageBaseDao.add(image);
            }

        }

    }

    @Override
    public Warehouse getOneById(int id) {

        return warehouseBaseDao.getOne(Warehouse.class,id);
    }

    @Override
    @Transactional
    public void delete(int id) throws Exception {

        //检查仓库下是否有仓单， rfid ， 摄像头， 如果有，不能删除
        String sql = "SELECT warehouse.id,  COUNT(DISTINCT tag.`no`) AS tagNumber , COUNT( DISTINCT receipt.`no`) AS receiptNumber ,  COUNT(DISTINCT camera.id) AS cameraNumber FROM warehouse \nLEFT JOIN tag ON tag.`warehouse_id`= warehouse.`id`\nLEFT JOIN camera ON camera.`warehouse_id` = warehouse.`id`\nLEFT JOIN receipt ON receipt.`warehouse_id` = warehouse.`id`\nWHERE warehouse.`id`=" + id;
        List result = this.warehouseBaseDao.createSqlQuery(sql);

        if(result != null && result.size() != 0) {
            Object[] objs = (Object[])result.get(0);
            int tagNumber = Integer.parseInt(objs[1].toString());
            int rgNumber = Integer.parseInt(objs[2].toString());
            int cameraNumber = Integer.parseInt(objs[3].toString());
            if(tagNumber > 0) {
                throw new Exception("仓库下有标签数据，不能删除");
            } else if(rgNumber > 0) {
                throw new Exception("仓库下有仓单数据，不能删除");
            } else if(cameraNumber > 0) {
                throw new Exception("仓库下有摄像头数据，不能删除");
            } else {

                //删除所有仓库图片
                DetachedCriteria where = DetachedCriteria.forClass(WarehouseImage.class);

                where.add(Restrictions.eq("warehouse.id",id));

                List<WarehouseImage> imageList = this.warehouseImageBaseDao.query(where);

                for(WarehouseImage image :imageList){

                    this.warehouseImageBaseDao.delete(image);
                }


                this.warehouseBaseDao.delete(this.warehouseBaseDao.getOne(Warehouse.class, Integer.valueOf(id)));
            }
        } else {
            throw new Exception("数据异常");
        }
    }

    @Override
    @Transactional
    public List<Warehouse> listForPage(Pager pager) {

        DetachedCriteria where = DetachedCriteria.forClass(Warehouse.class);

        //统计记录总数量
        Criteria criteria = where.getExecutableCriteria(warehouseBaseDao.getTemplate().getSessionFactory().getCurrentSession());

        Object count = criteria.setProjection(Projections.rowCount()).uniqueResult();

        pager.setRowCount(Integer.parseInt(count.toString()));

        //分页查询
        where.addOrder(Order.desc("id"));

        criteria.setProjection(null);

        List<Warehouse> warehouseList = criteria.setFirstResult(pager.firstResultIndex()).setMaxResults(pager.getPageSize()).list();

        System.out.println(warehouseList.size());

        return warehouseList;
    }

    @Override
    @Transactional
    public List<Warehouse> listByTypeForPage(int type, Pager pager) {

        DetachedCriteria where = DetachedCriteria.forClass(Warehouse.class);

        where.add(Restrictions.eq("type",type));

        //统计记录总数量
        Criteria criteria = where.getExecutableCriteria(warehouseBaseDao.getTemplate().getSessionFactory().getCurrentSession());

        Object count = criteria.setProjection(Projections.rowCount()).uniqueResult();

        pager.setRowCount(Integer.parseInt(count.toString()));

        //分页查询
        where.addOrder(Order.desc("id"));

        criteria.setProjection(null);

        List<Warehouse> warehouseList = criteria.setFirstResult(pager.firstResultIndex()).setMaxResults(pager.getPageSize()).list();

        System.out.println(warehouseList.size());

        return warehouseList;
    }

    @Override
    public List<WarehouseImage> getImageListByid(int id) {

        DetachedCriteria where = DetachedCriteria.forClass(WarehouseImage.class);

        where.add(Restrictions.eq("warehouse.id",id));
        where.addOrder(Order.desc("id"));

        return this.warehouseImageBaseDao.query(where);
    }

    @Override
    @Transactional
    public List<Warehouse> listByAreaAndPage(Pager pager, String area) {

        DetachedCriteria where = DetachedCriteria.forClass(Warehouse.class);

        where.add(Restrictions.like("address","%"+area+"%"));

        //统计记录总数量
        Criteria criteria = where.getExecutableCriteria(warehouseBaseDao.getTemplate().getSessionFactory().getCurrentSession());

        Object count = criteria.setProjection(Projections.rowCount()).uniqueResult();

        pager.setRowCount(Integer.parseInt(count.toString()));

        //分页查询
        where.addOrder(Order.desc("id"));

        criteria.setProjection(null);

        List<Warehouse> warehouseList = criteria.setFirstResult(pager.firstResultIndex()).setMaxResults(pager.getPageSize()).list();

        System.out.println(warehouseList.size());

        return warehouseList;
    }

    @Override
    @Transactional
    public List<WarehouseDto> getAllForDtoWithPage(Pager pager) {

        //统计总数量
        String countSql=" select count(id) from warehouse ";

        List countResult = this.warehouseBaseDao.createSqlQuery(countSql);

        BigInteger obj = (BigInteger) countResult.get(0);

        pager.setRowCount(obj.intValue());

        //执行分页查询
        String sql = "SELECT warehouse.*, COUNT(DISTINCT tag.`no`) AS tagNumber , COUNT(DISTINCT receipt.`no`) AS receiptNumber , COUNT( DISTINCT camera.id) AS cameraNumber " +
                "FROM warehouse \nLEFT JOIN tag ON tag.`warehouse_id`= warehouse.`id`\nLEFT JOIN camera ON camera.`warehouse_id` = warehouse.`id`\n " +
                "LEFT JOIN receipt ON receipt.`warehouse_id` = warehouse.`id`\nGROUP BY warehouse.`id` order by warehouse.`id` desc \n  limit "+ pager.firstResultIndex()+","+ pager.getPageSize();

        List result = this.warehouseBaseDao.createSqlQuery(sql);

        if(result==null || result.size()==0) return null;

        return getWarehouseDtoListByResult(result);

    }

    @Override
    @Transactional
    public List<WarehouseDto> searchByNameForDtoWithPage(Pager pager, String name) {

        //统计总数量
        String countSql=" select count(id) from warehouse where name like '%"+name.trim()+"%' ";

        List countResult = this.warehouseBaseDao.createSqlQuery(countSql);

        BigInteger obj = (BigInteger) countResult.get(0);

        pager.setRowCount(obj.intValue());

        //执行分页查询
        String sql = "SELECT warehouse.*, COUNT(DISTINCT tag.`no`) AS tagNumber , COUNT(DISTINCT receipt.`no`) AS receiptNumber , COUNT( DISTINCT camera.id) AS cameraNumber " +
                "FROM warehouse \nLEFT JOIN tag ON tag.`warehouse_id`= warehouse.`id`\nLEFT JOIN camera ON camera.`warehouse_id` = warehouse.`id`\n " +
                "LEFT JOIN receipt ON receipt.`warehouse_id` = warehouse.`id`\n where warehouse.name like '%"+name.trim()+"%'  GROUP BY warehouse.`id` order by warehouse.`id` desc \n  limit "+ pager.firstResultIndex()+","+ pager.getPageSize();

        List result = this.warehouseBaseDao.createSqlQuery(sql);

        if(result==null || result.size()==0) return null;

        return getWarehouseDtoListByResult(result);
    }

    @Override
    public List<Warehouse> searchByName(String name) {

        DetachedCriteria where = DetachedCriteria.forClass(Warehouse.class);

        where.add(Restrictions.like("name","%"+name+"%"));

        where.addOrder(Order.desc("id"));

        return this.warehouseBaseDao.query(where);
    }

    @Override
    @Transactional
    public List<Warehouse> listByAreaAndTypeAndPage(Pager pager, String area, int type) {

        DetachedCriteria where = DetachedCriteria.forClass(Warehouse.class);

        where.add(Restrictions.like("address","%"+area+"%"));
        where.add(Restrictions.eq("type",type));

        //统计记录总数量
        Criteria criteria = where.getExecutableCriteria(warehouseBaseDao.getTemplate().getSessionFactory().getCurrentSession());

        Object count = criteria.setProjection(Projections.rowCount()).uniqueResult();

        pager.setRowCount(Integer.parseInt(count.toString()));

        //分页查询
        where.addOrder(Order.desc("id"));

        criteria.setProjection(null);

        List<Warehouse> warehouseList = criteria.setFirstResult(pager.firstResultIndex()).setMaxResults(pager.getPageSize()).list();

        System.out.println(warehouseList.size());

        return warehouseList;
    }

    private List<WarehouseDto> getWarehouseDtoListByResult(List result) {

        if(result==null) return null;

        List<WarehouseDto> warehouseDtoList = new ArrayList<>();

        for (Object aResult : result) {

            Object[] obj = (Object[]) aResult;
            WarehouseDto dto = new WarehouseDto();
            dto.setId(Integer.parseInt(obj[0].toString()));
            dto.setAddress(obj[1].toString());
            dto.setContacts(obj[2].toString());
            dto.setContactsPhone(obj[3] == null ? "" : obj[3].toString());
            dto.setLat(Double.parseDouble(obj[4].toString()));
            dto.setLng(Double.parseDouble(obj[5].toString()));
            dto.setName(obj[6].toString());

            dto.setType(Integer.parseInt(obj[10].toString()));          //仓库类型
            dto.setTagNumber(Integer.parseInt(obj[11].toString()));     //标签数量
            dto.setReceiptNumber(Integer.parseInt(obj[12].toString())); //仓单数量
            dto.setCameraNumber(Integer.parseInt(obj[13].toString()));  //摄像头数量

            warehouseDtoList.add(dto);
        }

        return warehouseDtoList;
    }
}
